/***************************************************************************************************
 *Copyright(C),2010-2016,Sumscope
 *FileName	:  proto_message.cpp
 *Author	:  scofined.qi
 *Version	:  1.0
 *Date		:  2019/01/18
 *Desc		:  //用于主要说明此程序文件完成的主要功能
 *Relation :
 *Others	:  //其他内容说明
 *Function :  //主要函数列表，每条记录应包含函数名及功能简要说明
 *History	:
 * //修改历史记录列表，每条修改记录应包含修改日期、修改者及修改内容简介
 ***************************************************************************************************/
#include "include/proto_message.h"

#include <algorithm>

#include "core/thirdparty/zlib/zlib.h"
#include "include/JsonWriter.h"

#define FIELD_OFFSET2(type, field) ((long)(long long*)&(((type*)0)->field))
#define RTL_FIELD_SIZE2(type, field) (sizeof(((type*)0)->field))

namespace qb {
namespace base {
namespace msg {
#define Y_RD_SERVICE_MESSAGE_BLOCK_LEN 2048 * 20
bool bUnZip(char* in, int in_len, char* out, int* out_len) {
  z_stream strm;
  int ret;

  strm.zalloc = Z_NULL;
  strm.zfree = Z_NULL;
  strm.opaque = Z_NULL;
  strm.avail_in = 0;
  strm.next_in = Z_NULL;
  //	try
  {
    ret = inflateInit(&strm);
    if (ret != Z_OK) {
      return false;
    }
    strm.avail_in = in_len;
    strm.next_in = (Bytef*)in;
    strm.avail_out = Y_RD_SERVICE_MESSAGE_BLOCK_LEN;
    strm.next_out = (Bytef*)out;
    ret = inflate(&strm, Z_FINISH);
    if (ret == Z_DATA_ERROR || ret == Z_NEED_DICT || ret == Z_MEM_ERROR) {
      inflateEnd(&strm);
      return false;
    } else {
      *out_len = Y_RD_SERVICE_MESSAGE_BLOCK_LEN - strm.avail_out;
      inflateEnd(&strm);
      return true;
    }
  }
  //	catch (...)
  {
    //		inflateEnd(&strm);
    //		return false;
  }
}

static const std::string PropType = "Type.Prop";
static const std::string PropSubject = "Subject.Prop";
static const std::string PropMessageID = "MessageID.Prop";
bool IsCheckProtoMessageEnable() {
  static bool init = false;
  static bool enable = false;
  if (!init) {
    init = true;
    //	enable = cfg::GetConfigBool(kBaseConfigCheckProtoMessage); //syy
  }
  return enable;
}

#define MSGASSERT(smt)                                                      \
  if (IsCheckProtoMessageEnable()) {                                        \
    (void)((!!(smt)) ||                                                     \
           (qb::base::DbgError(#smt, __FILE__, __FUNCTION__, __LINE__, ""), \
            0));                                                            \
  }
#define MSGCHECKTYPE()                                                     \
  if (IsCheckProtoMessageEnable()) {                                       \
    BASSERTS(false, "NAME(%s)'s type is not expected:VAR_STRING  real:%d", \
             name, v.Type);                                                \
  }

enum kType : unsigned char {
  // 注意,此字段必须与proto库的bool Decoder::Decode(Variant&
  // var)里面的值保持一致
  kTypeInvalid = 0,
  kTypeBool = 0x08,
  kTypeInt8 = 0x02,
  kTypeUInt8 = 0x03,
  kTypeInt16 = 0x11,
  kTypeUInt16 = 0x12,
  kTypeInt32 = 0x21,
  kTypeUInt32 = 0x22,
  kTypeInt64 = 0x31,
  kTypeUInt64 = 0x32,

  kTypeFloat = 0x23,
  kTypeDouble = 0x33,

  kTypeString = 0x95,
  kTypeRaw1 = 0x80,
  kTypeRaw2 = 0x90,
  kTypeRaw4 = 0xa0,
  kTypeMap = 0xa8,
  kTypeList = 0xa9,
  kTypeVoid = 0xf0,
};

namespace {
struct DecodeData {
  union {
    bool b;
    int8_t i8;
    uint8_t u8;
    int16_t i16;
    uint16_t u16;
    int32_t i32;
    uint32_t u32;
    float f;
    int64_t i64;
    uint64_t u64;
    double d;
  } u;
};

template <int N>
DecodeData DecodeValue(const char* data) {
  DecodeData dd;
  dd.u.u8 = *((const uint8_t*)data);
  return dd;
}
template <>
DecodeData DecodeValue<2>(const char* data) {
  DecodeData dd;
  dd.u.u16 = (((uint8_t)data[0]) << 8) | ((uint8_t)data[1]);
  return dd;
}
template <>
DecodeData DecodeValue<4>(const char* data) {
  DecodeData dd;
  uint32_t a = (uint8_t)data[0];
  uint32_t b = (uint8_t)data[1];
  uint32_t c = (uint8_t)data[2];
  uint32_t d = (uint8_t)data[3];
  dd.u.u32 = (a << 24) | (b << 16) | (c << 8) | d;
  return dd;
}
template <>
DecodeData DecodeValue<8>(const char* data) {
  uint64_t hi = DecodeValue<4>(data).u.u32;
  uint64_t lo = DecodeValue<4>(data + 4).u.u32;
  DecodeData dd;
  dd.u.u64 = (hi << 32) | lo;
  return dd;
}

template <class T>
inline T DecodeOneValue(const char* data, const char* end, const T& fail) {
  if (data + sizeof(T) > end) return fail;
  DecodeData dd = DecodeValue<sizeof(T)>(data);
  return *((const T*)&dd);
}

#define DECODE_TYPE(TYPE, FAIL) DecodeOneValue(decode, end, (TYPE)(FAIL))
#define DECODE_DATA(DATA, TYPE) \
  DecodeOneValue(DATA, DATA + sizeof(TYPE), TYPE(0))

}  // namespace
ValueDict::ValueDict() : m_buffer(nullptr), m_capcity(1024) {}

ValueDict::~ValueDict() {
  if (m_buffer) delete[] m_buffer;
  m_buffer = nullptr;
}

bool ValueDict::Parse(const char* data, int len) {
  if (data == nullptr || len <= 0) return false;

  if (m_buffer == nullptr || m_capcity < Y_RD_SERVICE_MESSAGE_BLOCK_LEN) {
    if (m_buffer) delete[] m_buffer;
    m_capcity = Y_RD_SERVICE_MESSAGE_BLOCK_LEN;
    m_buffer = new char[m_capcity];
    memset(m_buffer, 0, m_capcity);
  }

  int size = 0;
  if (!bUnZip((char*)data, len, m_buffer, &size)) return false;

  char* buf = m_buffer;
  PackHeader head = *((PackHeader*)buf);
  std::vector<const char*> fields;
  fields.reserve(head.FieldCount);
  int pack_headsize = FIELD_OFFSET2(PackHeader, FieldCount) +
                      RTL_FIELD_SIZE2(PackHeader, FieldCount);
  const char* field_start = buf + pack_headsize;
  if (size <= pack_headsize) return false;
  if (head.tag != 0x53524244) return false;
  if (head.FieldCount > 1000) return false;
  for (int i = 0; i < head.FieldCount; i++) {
    fields.push_back(field_start);
    field_start += strlen(field_start) + 2;
  }
  int nfield = fields.size();
  const char* record_start = buf + head.StartPos + 8;
  if (record_start - buf >= size) return false;
  int typelens[kPackDateTypeCount] = {0,
                                      0,
                                      0,
                                      0,
                                      0,
                                      sizeof(int),
                                      0,
                                      0,
                                      0,
                                      0,
                                      1,
                                      0,
                                      sizeof(double),
                                      0,
                                      sizeof(time_t),
                                      0};  // 各个类型的数据长度,参见_SkipBuffer
  if (!IsValidDict(head, record_start, nfield)) return false;
  m_packsize = size;
  m_head = head;
  m_fields = fields;
  m_values.reserve(head.RecordCount * head.FieldCount);
  m_values.clear();
  time_t t = 0;
  Field val = {kPackDateTypeNone, 0, 0, 0, nullptr, nullptr};
  for (int i = 0; i < (int)head.RecordCount; i++) {
    const char* record = record_start;
    int ignore_col_count = 0;
    val.row = i;
    for (int j = 0; j < (int)head.FieldCount; j++) {
      val.col = j;
      val.type = kPackDateTypeNone;
      val.name = m_fields[j];
      val.data = nullptr;  // 默认值
      kPackDateType type = (kPackDateType)(*record);
      char gap = record[1];  // 类型之后的一个字节
      const char* data = record + 2;  // 变长的数据开始,长度由类型和内容决定
      if (gap != 0) {
        record = record + 2;
        ignore_col_count++;
        m_values.push_back(val);
        continue;
      }
      int len = 2 + typelens[type];
      int dlen = (type == kPackDateTypeString) ? strlen(data) : 0;
      len += dlen;
      if (j >= nfield)  // 此字段QB没有,忽略
      {
        record = record + len;
        m_values.push_back(val);
        continue;
      }
      val.type = type;
      val.data = data;
      switch (type) {
        case kPackDateTypeInt32:
          val.len = sizeof(int);
          break;
        case kPackDateTypeTime32:
          val.len = sizeof(time_t);
          break;
        case kPackDateTypeDouble:
          val.len = sizeof(double);
          break;
        case kPackDateTypeString:
          val.len = dlen;
          break;
        default:
          break;
      }
      record = record + len;
      m_values.push_back(val);
    }
    record_start = record + 8;  // 两条记录之间间隔8字节
  }
  if (m_values.size() != m_head.RecordCount * m_head.FieldCount) return false;
  return true;
}

bool ValueDict::GetValue(int row, int col, Field& value) const {
  size_t index = row * m_head.FieldCount + col;
  if (index >= 0 && index < m_values.size()) {
    value = m_values[index];
    return true;
  }
  return false;
}

const char* ValueDict::GetColName(int col) const {
  if (col >= 0 && col < (int)m_fields.size()) return m_fields[col];
  return nullptr;
}

bool ValueDict::IsValidDict(const PackHeader& head, const char* start,
                            int nfield) {
  int typelens[kPackDateTypeCount] = {0,
                                      0,
                                      0,
                                      0,
                                      0,
                                      sizeof(int),
                                      0,
                                      0,
                                      0,
                                      0,
                                      1,
                                      0,
                                      sizeof(double),
                                      0,
                                      sizeof(time_t),
                                      0};  // 各个类型的数据长度,参见_SkipBuffer
  const char* record_start = start;
  for (int i = 0; i < (int)head.RecordCount; i++) {
    const char* record = record_start;
    int ignore_col_count = 0;
    for (int j = 0; j < (int)head.FieldCount; j++) {
      kPackDateType type = (kPackDateType)(*record);
      char gap = record[1];  // 类型之后的一个字节
      const char* data = record + 2;  // 变长的数据开始,长度由类型和内容决定
      if (gap != 0) {
        // LOGWARN("ignore col:%d", j);
        record = record + 2;
        ignore_col_count++;
        continue;
      }
      int len = 2 + typelens[type];
      int dlen = (type == kPackDateTypeString) ? strlen(data) : 0;
      len += dlen;
      if (j >= nfield)  // 此字段QB没有,忽略
      {
        record = record + len;
        continue;
      }
      switch (type) {
        case kPackDateTypeInt32:
        case kPackDateTypeTime32:
        case kPackDateTypeDouble:
        case kPackDateTypeString:
          break;
        default:
          return false;
          break;
      }
      record = record + len;
    }
    record_start = record + 8;  // 两条记录之间间隔8字节
  }
  return true;
}

std::string Value::tostring() const {
  class ValueFormater {
    char buffer[256];

   public:
    ValueFormater(VarType t, const char* d, int s) {
      switch (t) {
        case Value::VAR_BOOL:
          FMTBUF(buffer, "bool:%s", *((bool*)d) ? "true" : "false");
          break;
        case Value::VAR_INT8:
          FMTBUF(buffer, "INT8:%c", *((int8_t*)d));
          break;
        case Value::VAR_UINT8:
          FMTBUF(buffer, "UINT8:%c", *((uint8_t*)d));
          break;
        case Value::VAR_INT16:
          FMTBUF(buffer, "INT16:%d", DECODE_DATA(d, int16_t));
          break;
        case Value::VAR_UINT16:
          FMTBUF(buffer, "UINT16:%d", DECODE_DATA(d, uint16_t));
          break;
        case Value::VAR_INT32:
          FMTBUF(buffer, "INT32:%d", DECODE_DATA(d, int32_t));
          break;
        case Value::VAR_UINT32:
          FMTBUF(buffer, "UINT32:%d", DECODE_DATA(d, uint32_t));
          break;
        case Value::VAR_INT64:
          FMTBUF(buffer, "INT64:%lld", DECODE_DATA(d, int64_t));
          break;
        case Value::VAR_UINT64:
          FMTBUF(buffer, "UINT64:%lld", DECODE_DATA(d, uint64_t));
          break;
        case Value::VAR_FLOAT:
          FMTBUF(buffer, "float:%f", DECODE_DATA(d, float));
          break;
        case Value::VAR_DOUBLE:
          FMTBUF(buffer, "double:%f", DECODE_DATA(d, double));
          break;
        case Value::VAR_VOID:
          FMTBUF(buffer, "void: ");
          break;
        case Value::VAR_RAW:
          FMTBUF(buffer, "raw:%d", s);
          break;
        case Value::VAR_STRING:
          FMTBUF(buffer, "string:%s", std::string(d, s).c_str());
          break;
        default:
          FMTBUF(buffer, "unknown:%d", s);
          break;
          break;
      }
    }
    const char* c_str() const { return buffer; }
  };

  ValueFormater fmt((VarType)Type, data, size);
  if (key) {
    char buf[1024] = {0};
    FMTBUF(buf, "%24s:%s", std::string(key, keylen).c_str(), fmt.c_str());
    return buf;
  }
  return fmt.c_str();
}

std::string Value::GetString() const {
  if (Type == Value::VAR_STRING && data) return std::string(data, size);
  return "";
}

bool Value::GetInt32(int& value) const {
  if (Type == Value::VAR_INT32) {
    value = operator int();
    return true;
  }
  return false;
}

bool Value::GetDouble(double& value) const {
  if (Type == Value::VAR_DOUBLE) {
    value = operator double();
    return true;
  }
  return false;
}

bool Value::RefString(const char*& value, size_t& size) const {
  if (Type == Value::VAR_STRING) {
    value = this->data;
    size = this->size;
    return true;
  }
  return false;
}

#define IMPL_OPERATOR(TYPE)                          \
  Value::operator TYPE() const {                     \
    DecodeData dd = DecodeValue<sizeof(TYPE)>(data); \
    return *((const TYPE*)&dd);                      \
  }

IMPL_OPERATOR(bool);
IMPL_OPERATOR(uint8_t);
IMPL_OPERATOR(uint16_t);
IMPL_OPERATOR(uint32_t);
IMPL_OPERATOR(uint64_t);
IMPL_OPERATOR(int8_t);
IMPL_OPERATOR(int16_t);
IMPL_OPERATOR(int32_t);
IMPL_OPERATOR(int64_t);
IMPL_OPERATOR(float);
IMPL_OPERATOR(double);

/////////////////////////////////////////////////////////////////////////////
const ValueList::const_iterator& ValueList::const_iterator::operator++() {
  Value nextv;
  Buffer buf(m_value.next(), m_scope.end() - m_value.next(), m_scope.count);
  if (Message::DecodeValue(buf, m_value.ptype == Value::VAR_MAP, nextv)) {
    nextv.level = m_value.level;
    nextv.msg = m_value.msg;
    nextv.ptype = m_value.ptype;
    nextv.parent = m_value.parent;
    m_value = nextv;
    m_index++;
  } else {
    m_scope = Buffer();
    m_value = Value();
    m_index = -1;
  }
  return *this;
}

ValueList::const_iterator ValueList::begin() const {
  Value subvalue;
  Buffer buf(m_value.data, m_value.size, m_value.count);
  if (Message::DecodeValue(buf, m_value.Type == Value::VAR_MAP, subvalue)) {
    subvalue.level = m_value.level + 1;
    subvalue.msg = m_value.msg;
    subvalue.ptype = m_value.Type;
    subvalue.parent = buf;
    return const_iterator(buf, subvalue, 0);
  }
  return m_end;
}

bool ValueMap::find(const char* name, Value& v) const {
  if (m_value.msg == nullptr) return false;
  return m_value.msg->find(name, *this, v);
}

bool ValueMap::GetString(const char* name, const char*& value,
                         size_t& size) const {
  Value v;
  if (find(name, v)) {
    if (v.Type == Value::VAR_STRING) {
      value = v.data;
      size = v.size;
      return true;
    }
  }
  return false;
}

bool ValueMap::GetMap(const char* name, ValueMap& vmap) const {
  Value v;
  if (find(name, v)) {
    if (v.Type == Value::VAR_MAP) {
      vmap = v;
      return true;
    }
  }
  return false;
}

bool ValueMap::GetList(const char* name, ValueList& vlist) const {
  Value v;
  if (find(name, v)) {
    if (v.Type == Value::VAR_LIST) {
      vlist = v;
      return true;
    }
  }
  return false;
}

bool ValueMap::GetRaw(const char* name, Raw& value) const {
  Value v;
  if (find(name, v)) {
    if (v.Type == Value::VAR_RAW) {
      value = Raw(v.data, v.size);
      return true;
    }
  }
  return false;
}

Message::Message() : m_bfind(0), m_sfind(0) {}
Message::~Message() {}
void Message::Clear() {
  // if (m_bfind > m_sfind)
  //{
  //	int bytes = m_header.value().bytes + m_map.value().bytes;
  //	const char* value = nullptr;
  //	size_t size = 0;
  //	m_header.GetString(PropType.c_str(), value, size);
  //	BLOGINFO("[MESSAGE][FIND]funcid:%s  bfind:%6d  sfind:%6d  length:%8d",
  //		value ? string(value,size).c_str() : "", m_bfind, m_sfind,
  //bytes);
  // }
  Value v;
  m_header = v;
  m_map = v;
  m_bfind = 0;
  m_sfind = 0;
}
int Message::decodeMap(const char* buf, int len, bool inMap) {
  // 只解析Map,忽略头部
  Value v;
  m_header = v;
  if (!DecodeValue(Buffer(buf, len), inMap, v, false)) {
    return -1;
  }
  v.msg = this;
  m_map = v;
  return v.bytes;
}
int Message::decode(const char* buf, int len) {
  // Message包含2个map,第一个是头部,第二个是body
  // 两个map都没有type字段和key,因此要忽略
  Value v;
  if (!DecodeValue(Buffer(buf, len), false, v, true)) {
    return -1;
  }
  v.parent = Buffer(buf, len);
  v.msg = this;
  m_header = v;
  if (!DecodeValue(Buffer(buf + v.bytes, len - v.bytes), false, v, true)) {
    return -1;
  }
  v.parent = Buffer(buf + v.bytes, len - v.bytes);
  v.msg = this;
  m_map = v;

  return m_header.value().bytes + v.bytes;
}

bool Message::DecodeValue(const Buffer& buf, bool inMap, Value& value,
                          bool skipType) {
  // 5个编码:KEY	TYPE	SIZE	COUNT	CONTENT
  // SIZE:只有list,map才有,指的是COUNT和CONTENT共同占据的大小
  const char* data = buf.data;

  int length = buf.size;
  if (data == nullptr || length < 1) return false;
  const char* end = data + length;
  const char* decode = data;

  // KEY
  Value v;
  if (inMap) {
    v.keylen = DECODE_TYPE(uint8_t, 0);  // 只支持最长256的key
    decode += sizeof(uint8_t);
    v.key = decode;
    decode += v.keylen;
    if (decode >= end) {
      return false;
    }
  } else {
    v.key = nullptr;
    v.keylen = 0;
  }
  // TYPE
  kType type = kTypeInvalid;
  if (skipType) {
    type = kTypeMap;
  } else {
    type = DECODE_TYPE(kType, kTypeInvalid);
    decode += sizeof(uint8_t);
  }

  if (type == kTypeInvalid) {
    return false;
  }

  // SIZE,COUNT,TYPE
  v.count = 0;
  switch (type) {
    case kTypeBool:
      v.size = sizeof(bool);
      v.Type = Value::VAR_BOOL;
      break;
    case kTypeInt8:
      v.size = sizeof(int8_t);
      v.Type = Value::VAR_INT8;
      break;
    case kTypeUInt8:
      v.size = sizeof(uint8_t);
      v.Type = Value::VAR_UINT8;
      break;
    case kTypeInt16:
      v.size = sizeof(int16_t);
      v.Type = Value::VAR_INT16;
      break;
    case kTypeUInt16:
      v.size = sizeof(uint16_t);
      v.Type = Value::VAR_UINT16;
      break;
    case kTypeInt32:
      v.size = sizeof(int32_t);
      v.Type = Value::VAR_INT32;
      break;
    case kTypeUInt32:
      v.size = sizeof(uint32_t);
      v.Type = Value::VAR_UINT32;
      break;
    case kTypeInt64:
      v.size = sizeof(int64_t);
      v.Type = Value::VAR_INT64;
      break;
    case kTypeUInt64:
      v.size = sizeof(uint64_t);
      v.Type = Value::VAR_UINT64;
      break;
    case kTypeFloat:
      v.size = sizeof(float);
      v.Type = Value::VAR_FLOAT;
      break;
    case kTypeDouble:
      v.size = sizeof(double);
      v.Type = Value::VAR_DOUBLE;
      break;
    case kTypeString:
      v.size = DECODE_TYPE(uint16_t, -1);  // see Encoder::EncodeString
      v.Type = Value::VAR_STRING;
      decode += sizeof(uint16_t);
      break;
    case kTypeRaw1:
      v.size = DECODE_TYPE(uint8_t, -1);  // see Encoder::EncodeRaw
      v.Type = Value::VAR_RAW;
      decode += sizeof(uint8_t);
      break;
    case kTypeRaw2:
      v.size = DECODE_TYPE(uint16_t, -1);
      v.Type = Value::VAR_RAW;
      decode += sizeof(uint16_t);
      break;
    case kTypeRaw4:
      v.size = DECODE_TYPE(uint32_t, -1);
      v.Type = Value::VAR_RAW;
      decode += sizeof(uint32_t);
      break;
    case kTypeList:
    case kTypeMap:
      v.Type = (type == kTypeList) ? Value::VAR_LIST : Value::VAR_MAP;
      v.size = DECODE_TYPE(uint32_t, -1);
      decode += sizeof(uint32_t);
      v.count = DECODE_TYPE(uint32_t, -1);
      decode += sizeof(uint32_t);
      v.size -= sizeof(uint32_t);  // 参考Encoder::EncodeMap中的size-5
      break;
    default:
      return false;
  }
  // CONTENT
  v.bytes = v.size + (decode - data);
  v.data = decode;
  if (v.size < 0 || v.count < 0 || decode > end || decode + v.size > end ||
      v.bytes <= 0) {
    return false;
  }
  value = v;
  return true;
}

bool Message::find(const char* name, const ValueMap& map, Value& v) {
  // 当m_field_table没有与map绑定的时候,需要立即重建
  Buffer buf(map.value().data, map.value().size);
  if (m_field_table.buffer() != buf) {
    m_field_table.rebuild(map);
  }
  FieldTable::kFindType type =
      m_field_table.getFieldValue(name, strlen(name), v);
  // m_bfind += (type == FieldTable::kFindTypeByBinary) ? 1 : 0;
  // m_sfind += (type == FieldTable::kFindTypeByOrder) ? 1 : 0;
  return type != FieldTable::kFindTypeFail;
}

//////////////////////////////////////////////////////////////////////////
namespace {
bool CheckNotExist(const Value* arr, int nsize, const char* name, int len) {
  int index = -1;
  for (int i = 0; i < nsize; i++) {
    const Value& val = arr[i];
    int cmp = FieldTable::CompString(name, len, val.key, val.keylen);
    if (cmp == 0) return false;
  }
  return true;
}
bool CheckSorted(const Value* arr, int nsize) {
  if (nsize <= 1) return true;
  for (int i = 1; i < nsize; i++) {
    int cmp = FieldTable::CompByKey(&arr[i - 1], &arr[i]);
    if (cmp > 0) return false;
  }
  return true;
}

}  // namespace
FieldTable::FieldTable() : m_lastpos(0) {}
void FieldTable::rebuild(const ValueMap& map) {
  m_lastpos = 0;
  m_signature = Buffer(map.value().data, map.value().size);
  m_values.Reset();

  for (ValueList::const_iterator it = map.begin(); it != map.end(); ++it) {
    const Value& v = *it;
    m_values.Add(v);
  }

  // if (0)
  //{
  //	// 实际找到的最大值是32,因此64是足够的
  //	static int maxSize = 0;
  //	if (maxSize < map.size())
  //	{
  //		maxSize = map.size();
  //		string names;
  //		for (int i = 0; i < m_values.size(); i++)
  //			names += string(m_values[i].key, m_values[i].keylen) +
  //string(","); 		BLOGINFO("[MESSAGE]max:%6d names:%s", maxSize, names.c_str());
  //	}
  // }

  // 确保m_values的数据是有序的
  if (m_values.size() > 1) {
    qsort(m_values.GetBuf(), m_values.size(), sizeof(Value),
          FieldTable::CompByKey);
  }
}
int FieldTable::CompString(const char* s1, int len1, const char* s2, int len2) {
  if (s1 && s2) {
    // 实测 如下代码比strncmp好太多太多!!!
    int len = len1 < len2 ? len1 : len2;
    int cmp = 0;
    for (int i = 0; i < len; i++) {
      if (s1[i] != s2[i]) {
        cmp = s1[i] < s2[i] ? (-1) : 1;
        break;
      }
    }
    return cmp != 0 ? cmp : (len1 == len2 ? 0 : (len1 < len2 ? (-1) : 1));
  }
  return s1 == s2 ? 0 : (!s1 ? (-1) : 1);
}
int FieldTable::CompByKey(const void* p1, const void* p2) {
  const Value* v1 = (const Value*)p1;
  const Value* v2 = (const Value*)p2;
  return CompString(v1->key, v1->keylen, v2->key, v2->keylen);
}

namespace {

int find_last(const FieldTable::ValueArray& values, int pos, const char* name,
              int len) {
  // 从pos往两边找,如果发现有名称与pos相同,继续找,直到找到最后一个与pos名称相同的为止
  // 原因在于:服务器后台可能在一个map下面,放置多个相同名称的值,取最后一个
  // 如果直接返回pos,那么忽略相同key的情况
  if (1) {
    int nsize = values.size();
    for (int k = pos + 1; k < nsize; ++k) {
      const Value& val = values[k];
      if (FieldTable::CompString(name, len, val.key, val.keylen) != 0) break;
      if (val.data > values[pos].data) pos = k;
    }
    for (int k = pos - 1; k >= 0; --k) {
      const Value& val = values[k];
      if (FieldTable::CompString(name, len, val.key, val.keylen) != 0) break;
      if (val.data > values[pos].data) pos = k;
    }
  }
  return pos;
}
}  // namespace
FieldTable::kFindType FieldTable::getFieldValue(const char* name, int len,
                                                Value& v) const {
  // 首先尝试上一次的位置开始搜索,2-3个位置
  // 再次使用二分法搜索
  // 利用cmp和pos,还可以进一步缩减bsearch的范围
  // 注意,原始服务器代码中,同一个map下面,可能存在若干个同名的value
  // 由于已经排序过
  if (m_values.size() <= 0) return kFindTypeFail;
  int start = m_lastpos == 0 ? (-1) : m_lastpos;
  int nsize = m_values.size();
  if (nsize <= 0) return kFindTypeFail;
  int cmp = 0, pos = 0, nmax = 3 < nsize ? 3 : nsize;
  for (int i = 0; i < nmax; i++) {
    pos = (i + start + 1) % nsize;
    const Value& val = m_values[pos];
    cmp = CompString(name, len, val.key, val.keylen);
    if (cmp == 0) {
      pos = find_last(m_values, pos, name, len);
      v = m_values[pos];
      (const_cast<FieldTable*>(this))->m_lastpos = pos;
      return kFindTypeByOrder;
    } else if (cmp < 0) {
      int last = pos - 1;
      cmp = last < 0 ? (1)
                     : (CompString(name, len, m_values[last].key,
                                   m_values[last].keylen));
      if (cmp == 0) {
        pos = find_last(m_values, last, name, len);
        v = m_values[pos];
        (const_cast<FieldTable*>(this))->m_lastpos = pos;
        return kFindTypeByOrder;
      }
      if (cmp > 0) {
        return kFindTypeFail;
      }
      break;
    }
  }
  (const_cast<FieldTable*>(this))->m_search.key = name;
  (const_cast<FieldTable*>(this))->m_search.keylen = len;

  const Value* arr = m_values;
  const Value* ret = nullptr;
  if (cmp < 0) {
    ret = (const Value*)bsearch(&m_search, arr, pos, sizeof(Value),
                                FieldTable::CompByKey);
  } else {
    ret = (const Value*)bsearch(&m_search, arr + pos + 1, nsize - pos - 1,
                                sizeof(Value), FieldTable::CompByKey);
  }
  if (ret) {
    pos = ret - arr;
    pos = find_last(m_values, pos, name, len);
    v = m_values[pos];
    (const_cast<FieldTable*>(this))->m_lastpos = pos;

    return kFindTypeByBinary;
  }

  return kFindTypeFail;
}
bool FieldTable::getFieldValue(int index, Value& v) const {
  if (index < 0 || index >= m_values.size()) return false;
  v = m_values.at(index);
  return true;
}

/////////////////////////////////////////////////////////////////////////////
bool ProtoMap::RefList(const char* name, const ProtoList*& pList) const {
  pList = nullptr;
  ValueList v;
  if (m_map.GetList(name, v)) {
    ProtoList* list = new ProtoList(v);
    (const_cast<ProtoMap*>(this))->m_reflist.push_back(list);
    pList = list;
    return true;
  }
  return false;
}

bool ProtoMap::RefMapFrom(const Message& msg, const char* name) {
  return msg.MapValue().GetMap(name, m_map);
}

bool ProtoMap::GetList(const char* name, ProtoList& list) const {
  ValueList vlist;
  if (m_map.GetList(name, vlist)) {
    list.SetList(vlist);
    return true;
  }
  return false;
}

bool ProtoMap::GetMap(const char* name, ProtoMap& map) const {
  ValueMap vmap;
  if (m_map.GetMap(name, vmap)) {
    map.SetMap(vmap);
    return true;
  }
  return false;
}

bool ProtoMap::RefString(const char* name, const char*& value,
                         size_t& size) const {
  return m_map.GetString(name, value, size);
}

bool ProtoMap::GetRaw(const char* name, Raw& value) const {
  return m_map.GetRaw(name, value);
}

//////////////////////////////////////////////////////////////////////////
ProtoMessage::ProtoMessage() {}
ProtoMessage::ProtoMessage(const ProtoMap& map) {
  Clear();
  const ValueMap& vmap = map;
  const Value& v = vmap.value();
  if (m_msg.decodeMap(v.start(), v.bytes, v.ptype == Value::VAR_MAP) < 0) {
  }
}
int ProtoMessage::decode(const char* buf, int len) {
  Clear();
  return m_msg.decode(buf, len);
}
void ProtoMessage::Clear() { m_msg.Clear(); }
int GetMapKeySize(const ProtoMap& cont, int level);
int GetListKeySize(const ProtoList& cont, int level);

int GetListKeySize(const ProtoList& cont, int level) {
  int keysum = 0;
  int index = 0;
  // list下面的map,第一个要忽略
  for (auto it = cont.begin(); it != cont.end(); ++it, ++index) {
    if (it->Type == Value::VAR_MAP) {
      const ProtoMap& msgmap = *it;
      if (index > 0) keysum += GetMapKeySize(msgmap, level + 1);
    } else if (it->Type == Value::VAR_LIST) {
      const ProtoList& msglist = *it;
      keysum += GetListKeySize(msglist, level + 1);
    } else if (it->key) {
      keysum += it->keylen + 1;
    }
  }
  return keysum;
}
int GetMapKeySize(const ProtoMap& cont, int level) {
  int keysum = 0;
  for (auto it = cont.begin(); it != cont.end(); ++it) {
    if (it->Type == Value::VAR_MAP) {
      const ProtoMap& msgmap = *it;
      keysum += GetMapKeySize(msgmap, level + 1);
    } else if (it->Type == Value::VAR_LIST) {
      const ProtoList& msglist = *it;
      keysum += GetListKeySize(msglist, level + 1);
    } else if (it->key) {
      keysum += it->keylen + 1;
    }
  }
  return keysum;
}
int ProtoMessage::GetAllKeySize() {
  ProtoMap pmap;
  pmap.SetMap(m_msg.MapValue());
  int keysum = 0;
  keysum = GetMapKeySize(pmap, 0);
  return keysum;
}
namespace {
std::string GetPattern(const ProtoList& cont);
std::string GetPattern(const ProtoMap& cont);
std::string GetPattern(const ProtoMap& cont) {
  auto it = cont.begin();
  if (!(it != cont.end())) return "map:{}";
  bool allTypeEqual = true;
  uint8_t fistType = it->Type;
  std::string pattern = "";
  int index = 0;
  for (; it != cont.end(); ++it) {
    if (it->Type != fistType) allTypeEqual = false;
  }
  for (it = cont.begin(); it != cont.end(); ++it, ++index) {
    if (index > 0) pattern += ",";
    if (it->key && it->keylen > 0)
      pattern += std::string(it->key, it->keylen);
    else
      pattern += std::string("null");
    if (allTypeEqual) continue;
    if (it->Type == Value::VAR_MAP) {
      const ProtoMap& msgmap = *it;
      pattern += std::string(":") + GetPattern(msgmap);

    } else if (it->Type == Value::VAR_LIST) {
      const ProtoList& msglist = *it;
      pattern += std::string(":") + GetPattern(msglist);
    }
  }
  return pattern;
}
std::string GetPattern(const ProtoList& cont) {
  auto it = cont.begin();
  if (!(it != cont.end())) return "list:{}";
  bool allTypeEqual = true;
  uint8_t fistType = it->Type;
  cont.size();
  for (; it != cont.end(); ++it) {
    if (it->Type != fistType) return "list:{...}";
    if (it->Type == Value::VAR_MAP) {
      const ProtoMap& msgmap = *it;
      char buf[1024] = {0};
      FMTBUF(buf, "records:%d{%s}", cont.size(), GetPattern(msgmap).c_str());
      return buf;
    } else if (it->Type == Value::VAR_LIST) {
      const ProtoList& msglist = *it;
      return "list:" + GetPattern(msglist);
    } else {
      return "list:{v}";
    }
  }
  return "list:{}";
}
class JsonBuilder : public qb::base::JsonWriter {
  typedef unsigned int uint;
  typedef unsigned short ushort;
  struct PackHeader {   // 更新包中的数据头部
    uint tag;           // 文件开头的4个字节,0x44425253
    uint StartPos;      // 记录开始的偏移量
    uint RecordCount;   // 记录个数
    ushort FieldCount;  // 每条记录的字段个数
  };
  /*
  QB收到的字典数据包中的数据类型编码,目前只用到int32,string,double,time32四种类型
  */
  enum kPackDateType {
    kPackDateTypeNone = 0,
    kPackDateTypeInt8 = 1,
    kPackDateTypeUInt8 = 2,
    kPackDateTypeInt16 = 3,
    kPackDateTypeUInt16 = 4,
    kPackDateTypeInt32 = 5,
    kPackDateTypeUint32 = 6,
    kPackDateTypeInt64 = 7,
    kPackDateTypeUInt64 = 8,
    kPackDateTypeBool = 9,
    kPackDateTypeString = 10,
    kPackDateTypeFloat = 11,
    kPackDateTypeDouble = 12,
    kPackDateTypeRaw = 13,
    kPackDateTypeTime32 = 14,  // 等同于time_t，精度秒
    kPackDateTypeTime64 = 15,  // 等同于time_t + 毫秒，精度毫秒
    kPackDateTypeCount = 16
  };

 public:
  typedef qb::base::JsonWriter JsonWriter;
  typedef qb::base::JsonWriter::JsonWriterMap WMap;
  typedef qb::base::JsonWriter::JsonWriterList WList;

 protected:
  JsonWriter m_writer;
  IRawParser* m_rawParser;

 public:
  JsonBuilder(IRawParser* rawParser = nullptr) : m_rawParser(rawParser) {}
  void AddValueList(WList& parent, const ValueList& vmap) {
    for (auto it = vmap.begin(); it != vmap.end(); ++it) {
      if (it->Type == Value::VAR_MAP) {
        const ValueMap& msgmap = *it;
        WMap node = parent.AddMap();
        AddValueMap(node, msgmap);
      } else if (it->Type == Value::VAR_LIST) {
        const ValueList& msglist = *it;
        WList node = parent.AddList();
        AddValueList(node, msglist);
      } else {
        AddValue(parent, *it);
      }
    }
  }
  void AddValueMap(WMap& parent, const ValueList& vmap) {
    for (auto it = vmap.begin(); it != vmap.end(); ++it) {
      if (it->Type == Value::VAR_MAP) {
        const ProtoMap& msgmap = *it;
        WMap node = parent.AddMap(std::string(it->key, it->keylen).c_str());
        AddValueMap(node, msgmap);
      } else if (it->Type == Value::VAR_LIST) {
        const ValueList& msglist = *it;
        WList node = parent.AddList(std::string(it->key, it->keylen).c_str());
        AddValueList(node, msglist);
      } else {
        AddValue(parent, *it);
      }
    }
  }
  bool IsValidDict(const PackHeader& head, const char* start, int nfield) {
    int typelens[kPackDateTypeCount] = {
        0,
        0,
        0,
        0,
        0,
        sizeof(int),
        0,
        0,
        0,
        0,
        1,
        0,
        sizeof(double),
        0,
        sizeof(time_t),
        0};  // 各个类型的数据长度,参见_SkipBuffer
    const char* record_start = start;
    for (int i = 0; i < (int)head.RecordCount; i++) {
      const char* record = record_start;
      int ignore_col_count = 0;
      for (int j = 0; j < (int)head.FieldCount; j++) {
        kPackDateType type = (kPackDateType)(*record);
        char gap = record[1];  // 类型之后的一个字节
        const char* data = record + 2;  // 变长的数据开始,长度由类型和内容决定
        if (gap != 0) {
          // LOGWARN("ignore col:%d", j);
          record = record + 2;
          ignore_col_count++;
          continue;
        }
        int len = 2 + typelens[type];
        int dlen = (type == kPackDateTypeString) ? strlen(data) : 0;
        len += dlen;
        if (j >= nfield)  // 此字段QB没有,忽略
        {
          record = record + len;
          continue;
        }
        switch (type) {
          case kPackDateTypeInt32:
          case kPackDateTypeTime32:
          case kPackDateTypeDouble:
          case kPackDateTypeString:
            break;
          default:
            return false;
            break;
        }
        record = record + len;
      }
      record_start = record + 8;  // 两条记录之间间隔8字节
    }
    return true;
  }
  bool AddRaw(WMap& parent, const std::string& key, const char* sBuffer,
              int length) {
    // 首先,判断raw数据是否是字典格式
    // 如果不是,那么parent.AddString(key, "#raw");
    ValueDict dict;
    if (dict.Parse(sBuffer, length)) {
      int row = dict.GetRowCount();
      int col = dict.GetColCount();
      ValueDict::Field value;
      time_t t = 0;
      WList wlist = parent.AddList(key.c_str());
      for (int i = 0; i < row; i++) {
        WMap wmap = wlist.AddMap();
        for (int j = 0; j < col; j++) {
          if (!dict.GetValue(i, j, value) || value.data == nullptr) continue;
          switch (value.type) {
            case 5:
              wmap.AddInt(value.name, *(int*)value.data);
              break;
            case 14:
              t = *(time_t*)value.data;
              if (sizeof(time_t) == sizeof(int))
                wmap.AddInt(value.name, (int)t);
              else
                wmap.AddInt64(value.name, t);
              break;
            case 12:
              wmap.AddDouble(value.name, *(double*)value.data);
              break;
            case 10:
              wmap.AddString(value.name, (const char*)value.data, value.len);
              break;
            default:
              break;
          }
        }
      }
      return true;
    }

    /*
            外部可以在调用ProtoMessage::ToJson的时候,提供
            一个实现了IRawParser的解码器
            比如解析table格式的解码器,作为额外的第二个参数
            如果顺利解析,将会在原始json中增加解析后的消息
    */
    if (m_rawParser && m_rawParser->Parse(sBuffer, length)) {
      typedef IRawParser::kExpectType kExpectType;
      WList wlist = parent.AddList(key.c_str());
      int row = m_rawParser->GetRow();
      int col = m_rawParser->GetCol();
      double dvalue = 0;
      long long ivalue = 0;
      const long long i32max = ((long long)1UL) << 31;
      const long long u32max = ((long long)1UL) << 32;
      for (int i = 0; i < row; i++) {
        WMap wmap = wlist.AddMap();
        for (int k = 0; k < col; k++) {
          if (m_rawParser->IsCellDefault(i, k)) continue;
          kExpectType type = m_rawParser->GetColType(k);
          const char* name = m_rawParser->GetColName(k);
          switch (type) {
            case IRawParser::kExpectTypeInt:
              m_rawParser->GetCellValue(i, k, ivalue);
              if (ivalue < i32max)
                wmap.AddInt(name, (int)ivalue);
              else if (ivalue < u32max)
                wmap.AddUint(name, (unsigned int)ivalue);
              else
                wmap.AddInt64(name, ivalue);
              break;
            case IRawParser::kExpectTypeDouble:
              m_rawParser->GetCellValue(i, k, dvalue);
              wmap.AddDouble(name, dvalue);
              break;
            case IRawParser::kExpectTypeString: {
              int len = 0;
              const char* str = nullptr;
              m_rawParser->GetCellValue(i, k, str, len);
              wmap.AddString(name, str, len);
            } break;
            default:
              break;
          }
        }
      }
      return true;
    }
    return false;
    // static char buf[Y_RD_SERVICE_MESSAGE_BLOCK_LEN] = { 0 };
    // int size = 0;
    // if (!bUnZip((char*)sBuffer, length, buf, &size))
    //	return false;

    // PackHeader head = *((PackHeader*)buf);
    // vector<const char*> fields; fields.reserve(head.FieldCount);
    // int pack_headsize = FIELD_OFFSET(PackHeader, FieldCount) +
    // RTL_FIELD_SIZE(PackHeader, FieldCount); const char* field_start = buf +
    // pack_headsize; if (size <= pack_headsize) 	return false; if (head.tag !=
    // 0x53524244) 	return false; if (head.FieldCount > 1000) 	return false; for
    // (int i = 0; i < head.FieldCount; i++)
    //{
    //	fields.push_back(field_start);
    //	field_start += strlen(field_start) + 2;
    // }
    // int nfield = fields.size();
    // const char* record_start = buf + head.StartPos + 8;
    // if (record_start - buf >= size)
    //	return false;
    // int typelens[kPackDateTypeCount] = { 0, 0, 0, 0, 0,
    //	sizeof(int), 0, 0, 0, 0,
    //	1, 0, sizeof(double), 0, sizeof(time_t), 0
    // };// 各个类型的数据长度,参见_SkipBuffer
    // if (!IsValidDict(head, record_start, nfield))
    //	return false;
    // time_t t = 0;
    // WList wlist = parent.AddList(key.c_str());
    // for (int i = 0; i < (int)head.RecordCount; i++)
    //{
    //	const char* record = record_start;
    //	int ignore_col_count = 0;
    //	WMap wmap = wlist.AddMap();
    //	for (int j = 0; j < (int)head.FieldCount; j++)
    //	{
    //		kPackDateType type = (kPackDateType)(*record);
    //		char gap = record[1];//类型之后的一个字节
    //		const char* data = record + 2;	//
    //变长的数据开始,长度由类型和内容决定 		if (gap != 0)
    //		{
    //			//LOGWARN("ignore col:%d", j);
    //			record = record + 2;
    //			ignore_col_count++;
    //			continue;
    //		}
    //		int len = 2 + typelens[type];
    //		int dlen = (type == kPackDateTypeString) ? strlen(data) : 0;
    //		len += dlen;
    //		if (j >= nfield )	// 此字段QB没有,忽略
    //		{
    //			record = record + len;
    //			continue;
    //		}
    //		switch (type)
    //		{
    //		case
    //kPackDateTypeInt32:wmap.AddInt(fields[j],*(int*)data);break; 		case
    //kPackDateTypeTime32: 			t = *(time_t*)data; 			if (sizeof(time_t)==sizeof(int))
    //				wmap.AddInt(fields[j], t);
    //			else
    //				wmap.AddInt64(fields[j], t);
    //			break;
    //		case kPackDateTypeDouble:wmap.AddDouble(fields[j],
    //*(double*)data); break; 		case kPackDateTypeString:wmap.AddString(fields[j],
    //(const char*)data,dlen); break; 		default:break;
    //		}
    //		record = record + len;
    //	}
    //	record_start = record + 8;//两条记录之间间隔8字节
    // }
    // return true;
  }
  void AddValue(WList& parent, const Value& v) {
    switch (v.Type) {
      case Value::VAR_VOID:
        break;
      case Value::VAR_BOOL:
        parent.AddBool(v);
        break;
      case Value::VAR_INT8:
        parent.AddInt(v);
        break;
      case Value::VAR_UINT8:
        parent.AddUint(v);
        break;
      case Value::VAR_INT16:
        parent.AddInt(v);
        break;
      case Value::VAR_UINT16:
        parent.AddUint(v);
        break;
      case Value::VAR_INT32:
        parent.AddInt(v);
        break;
      case Value::VAR_UINT32:
        parent.AddUint(v);
        break;
      case Value::VAR_INT64:
        parent.AddInt64(v);
        break;
      case Value::VAR_UINT64:
        parent.AddUint64(v);
        break;
      case Value::VAR_FLOAT:
        parent.AddDouble(v);
        break;
      case Value::VAR_DOUBLE:
        parent.AddDouble(v);
        break;
      case Value::VAR_STRING: {
        const char* str = nullptr;
        size_t len = 0;
        if (v.RefString(str, len))
          parent.AddString(str, len);
        else
          parent.AddString("");
      } break;
      case Value::VAR_RAW: {
        parent.AddString("#raw");
      } break;
      default:
        break;
    }
  }
  void AddValue(WMap& parent, const Value& v) {
    std::string key = v.GetKey();
    const char* k = key.c_str();
    switch (v.Type) {
      case Value::VAR_VOID:
        break;
      case Value::VAR_BOOL:
        parent.AddBool(k, (bool)v);
        break;
      case Value::VAR_INT8:
        parent.AddInt(k, (int8_t)v);
        break;
      case Value::VAR_UINT8:
        parent.AddUint(k, (uint8_t)v);
        break;
      case Value::VAR_INT16:
        parent.AddInt(k, (int16_t)v);
        break;
      case Value::VAR_UINT16:
        parent.AddUint(k, (uint16_t)v);
        break;
      case Value::VAR_INT32:
        parent.AddInt(k, (int32_t)v);
        break;
      case Value::VAR_UINT32:
        parent.AddUint(k, (uint32_t)v);
        break;
      case Value::VAR_INT64:
        parent.AddInt64(k, (int64_t)v);
        break;
      case Value::VAR_UINT64:
        parent.AddUint64(k, (uint64_t)v);
        break;
      case Value::VAR_FLOAT:
        parent.AddDouble(k, (float)v);
        break;
      case Value::VAR_DOUBLE:
        parent.AddDouble(k, (double)v);
        break;
      case Value::VAR_STRING: {
        const char* str = nullptr;
        size_t len = 0;
        if (v.RefString(str, len) && len > 0)
          parent.AddString(k, str, len);
        else
          parent.AddString(k, "");
      } break;
      case Value::VAR_RAW: {
        if (!AddRaw(parent, key, v.data, v.size))
          parent.AddString(key.c_str(), "#raw");
      } break;
      default:
        break;
    }
  }
};
}  // namespace

int ProtoMessage::ToJson(std::string& str) { return ToJson(str, nullptr); }
int ProtoMessage::ToJson(std::string& str, IRawParser* rawParser) {
  JsonBuilder builder(rawParser);
  builder.SetFormat();
  JsonBuilder::WMap root = builder.AddRootMap();
  {
    JsonBuilder::WMap jhead = root.AddMap("head");
    builder.AddValueMap(jhead, m_msg.Header());
  }
  {
    JsonBuilder::WMap jbody = root.AddMap("body");
    builder.AddValueMap(jbody, m_msg.MapValue());
  }
  root.End();
  str = builder.c_str();
  return str.size();
}

void ProtoMessage::Dump(int fid) {
  int keysum = GetAllKeySize();
  int total = m_msg.Header().value().bytes + m_msg.MapValue().value().bytes;
  ProtoMap pmap;
  pmap.SetMap(m_msg.MapValue());
  std::string pattern = GetPattern(pmap);

  // 将所有消息先保存到本地
  if (0) {
    /*	static int id = 0;
            char fname[MAX_PATH] = { 0 };
            SYSTEMTIME st;
            GetLocalTime(&st);
            FMTBUF(fname,
       "./data/msg/%05d_%08d_%05d_%08d_%02d%02d%02d_%03d.msg",
                    GetCurrentProcessId(), id++, fid, total,
                    st.wHour, st.wMinute, st.wSecond, st.wMilliseconds
                    );
            const char* fdata = m_msg.Header().value().parent.data;
            StringUtil::SaveFileContent(fdata, total, fname);*/ //syy
  }

  if (pattern.size() > 1024) {
    pattern = pattern.substr(0, 1024);
  } else {
  }
}
bool ProtoMessage::GetList(const char* name, ProtoList& list) const {
  ValueList v;
  if (m_msg.MapValue().GetList(name, v)) {
    list.SetList(v);
    return true;
  }
  return false;
}
std::string ProtoMessage::GetType() const {
  const char* value = nullptr;
  size_t size = 0;
  if (m_msg.Header().GetString(PropType.c_str(), value, size) && value)
    return std::string(value, size);
  return "";
}
std::string ProtoMessage::getType() const { return GetType(); }
std::string ProtoMessage::GetMessageID() const {
  const char* value = nullptr;
  size_t size = 0;
  if (m_msg.Header().GetString(PropMessageID.c_str(), value, size) && value)
    return std::string(value, size);
  return "";
}
std::string ProtoMessage::getMessageID() const { return GetMessageID(); }
std::string ProtoMessage::GetSubject() const {
  const char* value = nullptr;
  size_t size = 0;
  if (m_msg.Header().GetString(PropSubject.c_str(), value, size) && value)
    return std::string(value, size);
  return "";
}
std::string ProtoMessage::getSubject() const { return GetSubject(); }

//////////////////////////////////////////////////////////////////////////
void ValueList::print(int level) const {
  for (const_iterator it = begin(); it != end(); ++it) {
    const Value& v = *it;
    if (v.Type == Value::VAR_LIST) {
      ValueList vlist(v);
      vlist.print(level + 1);
    } else if (v.Type == Value::VAR_MAP) {
      ValueMap vmap(v);
      vmap.print(level + 1);
    } else
      printf("\n%4d:%4d\t:  %s", it.size(), it.index(), v.tostring().c_str());
  }
}
void Message::print() const {
  m_header.print();
  m_map.print();
}
}  // namespace msg
}  // namespace base
}  // namespace qb
